home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9212.ZIP / sound.asc < prev    next >
Text File  |  1992-11-30  |  11KB  |  279 lines

  1. _SOUND AS A DATA TYPE_
  2. by Aaron E. Walsh
  3.  
  4. [LISTING ONE]
  5.  
  6. /************************************************************************/
  7. /* AddSoundTrackToMovie.c -- QuickTime program demonstrating how to add */
  8. /*  a sound track to a movie using data found in an snd sound resource. */
  9. /*  by Aaron E. Walsh Developed using Symantec Think C 5.0 and          */ 
  10. /*  Apple QuickTime headers                                         */
  11. /************************************************************************/
  12.  
  13. #include <Types.h>
  14. #include <Dialogs.h>
  15. #include <Sound.h>  
  16. #include <Movies.h> 
  17. #include <MoviesFormat.h>
  18.  
  19. #define     defaultChunkSize    32768
  20.  
  21. void    main(void);
  22. OSErr   InitMacManagers(void); 
  23. void    doSoundToMovie(void);
  24. OSErr OpenSndFile(short vRef, Str255 fileName, short *rRef, 
  25.                                                          Handle *soundHandle);
  26. void    ConvertSndToMovie(short destVolume, Str255 destName, Handle sndH,
  27.                                    long chunkSize, Boolean CreateFile);
  28. OSErr CreateSndDescriptor(Handle sndHandle, SoundDescriptionPtr sndDescriptP,
  29.                  unsigned long *dataOffset,unsigned long *frameCount);
  30.     
  31. /***** main() -- simple main event loop ******/
  32. void main() 
  33. {   
  34.     OSErr   error;
  35.     error = InitMacManagers(); 
  36.     if (!error)
  37.         {
  38.         doSoundToMovie();   /* focus of this article */
  39.         ExitMovies();       /* exit Movie Toolbox when done */  
  40.         }
  41. } /*main*/
  42.  
  43. /***** InitMacManagers() -- Initialize Toolbox Managers used here app. *****/
  44. OSErr   InitMacManagers() 
  45. {
  46.     OSErr   error;
  47.     InitGraf(&qd.thePort);
  48.     FlushEvents(everyEvent,0);
  49.     InitWindows();
  50.     InitDialogs(nil);
  51.     InitCursor();
  52.     
  53.     MaxApplZone();
  54.     
  55.     /* attempt to initialize the Movie Toolbox:  a better approach  */
  56.     /* would be to use the Gestalt Manager, as detailed in my   */
  57.     /* July 1992 DDJ article "Programming QuickTime"        */
  58.     
  59.     error = EnterMovies();      
  60.     return (error);
  61. } /*InitMacManagers*/
  62.  
  63. /**** doSoundToMovie() -- simple interface: select sound file & add it as a */
  64. /* QT sound track ****/
  65. void doSoundToMovie()
  66. {
  67.     Point           where;  
  68.     SFReply         userReply;
  69.     Handle          soundResourceHandle = nil;
  70.     short           resourceRefNum = 0;
  71.     OSErr           soundFileSelectErr, movieFileSelectErr;
  72.     SFTypeList      movieFileTypes;
  73.     
  74.     
  75.     soundFileSelectErr=movieFileSelectErr = 1; /* initialize error flags */
  76.     
  77.     /* select sound file: */
  78.     SFGetFile(where, "\p", nil, -1, nil, nil, &userReply);  
  79.     if (userReply.good)
  80.             soundFileSelectErr = OpenSndFile  (userReply.vRefNum, 
  81.                          userReply.fName, 
  82.                              &resourceRefNum, 
  83.                          &soundResourceHandle 
  84.                          );
  85.     /* select movie file: */        
  86.     movieFileTypes[0] = 'MooV';
  87.     SFGetFile(where, "\p", nil, 1, movieFileTypes, nil, &userReply);
  88.     movieFileSelectErr = !userReply.good; 
  89.         
  90.     if (!soundFileSelectErr && !movieFileSelectErr)
  91.                ConvertSndToMovie(userReply.vRefNum, userReply.fName, 
  92.                                 soundResourceHandle, defaultChunkSize, false);
  93.     else
  94.         SysBeep(1); /* beep to indicate conversion wasn't done */
  95. } /*doSoundToMovie()*/
  96.  
  97. /** OpenSndFile() -- open given file and retrieve first snd resource found **/
  98. OSErr OpenSndFile(short volRefNum, Str255 fileName, short *refNum, 
  99.                                                             Handle *soundHand)
  100. {
  101.     FSSpec              fileSpec;
  102.     OSErr               error;
  103.     short               saveResFile;
  104.  
  105.     /* create file specification record: */
  106.     error = FSMakeFSSpec(volRefNum, 0, fileName, &fileSpec);
  107.     if (error) DebugStr("\pFSMakeFSSpec Failed");
  108.  
  109.     if (*refNum)
  110.     {
  111.         CloseResFile(*refNum);  /* close file once spec is created */
  112.         if (error = ResError()) DebugStr("\pCloseResFile Failed");
  113.         *refNum = 0;
  114.     }
  115.     *refNum = FSpOpenResFile(&fileSpec, fsRdPerm);  /* open using spec */
  116.     if (*refNum < 0) DebugStr("\pFSpOpenResFile Failed");
  117.  
  118.     saveResFile = CurResFile(); /* save current resource refnum */
  119.     UseResFile(*refNum);        /* switch to our newly opened file */
  120.     if (error = ResError()) DebugStr("\pUseResFile Failed");
  121.  
  122.     *soundHand = Get1IndResource('snd ', 1); /* get first snd resource */
  123.     error = ResError();
  124.     UseResFile(saveResFile);
  125.     
  126.     if (!*soundHand)
  127.         error = -1;  /* return error if sound handle is nil */
  128.     return (error);
  129. } /*OpenSndFile*/
  130.  
  131. /* ConvertSndToMovie()--create new movie sound track from snd resource data */
  132. void ConvertSndToMovie(short destVolume, Str255 destName, Handle soundHand,
  133.                        long chunkSize, Boolean CreateFile)
  134. {
  135.     FSSpec              destSpec;
  136.     short               resID = 1;
  137.     short               resRefNum;
  138.     OSErr               theErr;
  139.     Track               sndTrack = 0;
  140.     Media               sndMedia = 0;
  141.     Movie               theMovie;
  142.     unsigned long       sndSize, bytes, dataOffset, numSampleFrames;
  143.     unsigned long       totalSamples, chunkSamples, samples;
  144.     unsigned long       bytesPerFrame, samplesPerFrame;
  145.     SoundDescription    **descH;
  146.     SoundDescription    *sndDescP;
  147.     
  148.        descH = (SoundDescription **) NewHandleClear( sizeof(SoundDescription));
  149.        if (!descH) DebugStr("\pCould not get description handle");
  150.  
  151.        sndDescP = *descH;
  152.     
  153.        CreateSndDescriptor(soundHand, sndDescP, &dataOffset, &numSampleFrames);
  154.        bytesPerFrame = 1;
  155.        samplesPerFrame = 1;
  156.     
  157.     theErr = FSMakeFSSpec(destVolume, 0, destName, &destSpec);
  158.     if (theErr == fnfErr) theErr = 0;
  159.     if (theErr) DebugStr("\pFSMakeFSSpec Failed");
  160.  
  161.     theErr = OpenMovieFile(&destSpec, &resRefNum, fsRdWrPerm); // ALTERED!
  162.     if (theErr) DebugStr("\pOpenMovieFile Failed");
  163.  
  164.     resID = 0;
  165.     theErr = NewMovieFromFile(&theMovie,resRefNum,&resID,destName,0,0L );
  166.     if (theErr) DebugStr("\pNewMovieFromFile Failed");
  167.         
  168.     /* Now put it into a track */
  169.     sndTrack = NewMovieTrack(theMovie, 0, 0, 255);
  170.     if (theErr = GetMoviesError()) DebugStr("\pNewMovieTrack Failed");
  171.  
  172.     sndMedia = NewTrackMedia(sndTrack, SoundMediaType, 
  173.                           ((unsigned long)(*descH)->sampleRate) >> 16, nil, 0);
  174.     sndSize = GetHandleSize(soundHand) - dataOffset;
  175.  
  176.     bytes = numSampleFrames * bytesPerFrame;  /* number of bytes 
  177.                                                    we expect in file */
  178.     if (bytes > sndSize)    /* sample too large */
  179.     {               
  180.         SysBeep(1); /* give a beep to indication error occured */
  181.         numSampleFrames = sndSize / bytesPerFrame;
  182.     }
  183.     totalSamples = numSampleFrames * samplesPerFrame; /* samples in file */
  184.  
  185.     if (!chunkSize)
  186.         chunkSamples = totalSamples;    /* all in one chunk */
  187.     else
  188.         chunkSamples = (chunkSize * samplesPerFrame) / bytesPerFrame;
  189.                                              /* get size of chunk in samples */
  190.     theErr = BeginMediaEdits( sndMedia );
  191.     if (theErr) DebugStr("\pBeginMediaEdits Failed");
  192.     while (totalSamples)
  193.     {
  194.         samples = totalSamples;                                 /* samples in chunk */
  195.         if (samples > chunkSamples)
  196.             samples = chunkSamples;
  197.         bytes = (samples * bytesPerFrame) / samplesPerFrame; 
  198.                                                           /* bytes in chunk */
  199.         theErr = AddMediaSample( sndMedia, soundHand, dataOffset, 
  200.                                bytes, (TimeValue) 1, (SampleDescriptionHandle)
  201.                                descH, samples, 0, 0);
  202.         if (theErr) DebugStr("\pAddMediaSample Failed");
  203.         dataOffset += bytes;
  204.         totalSamples -= samples;
  205.     }
  206.     theErr = EndMediaEdits( sndMedia );
  207.     if (theErr) DebugStr("\pEndMediaEdits Failed");
  208.     
  209.     theErr = InsertMediaIntoTrack(sndTrack,0L,0L,
  210.                                           GetMediaDuration(sndMedia), 0x10000);
  211.     if (theErr) DebugStr("\pInsertMediaIntoTrack Failed");
  212.  
  213.     /* Write out the movie */
  214.     DisposHandle((Handle) descH);
  215.     if (CreateFile)
  216.     {
  217.         theErr = AddMovieResource( theMovie, resRefNum, &resID, destName );
  218.         if (theErr) DebugStr("\pAddMovieResource Failed");
  219.     }
  220.     else
  221.     {
  222.       theErr = UpdateMovieResource( theMovie, resRefNum, resID, destName );
  223.       if (theErr) DebugStr("\pUpdateMovieResource Failed");
  224.     }
  225.     theErr = CloseMovieFile( resRefNum);
  226.     if (theErr) DebugStr("\pCloseMovieFile Failed");
  227.     DisposeMovie(theMovie);
  228. }/*ConvertSndToMovie*/
  229.  
  230. /**** CreateSndDescriptor() -- create a Sound Descriptor record from  */
  231. /*                             snd resource data ****/
  232. OSErr CreateSndDescriptor(Handle sndHandle, SoundDescriptionPtr sndDescriptP,
  233.         unsigned long *dataOffset,unsigned long *frameCount)
  234. {   
  235.     short   *i, synthCount, sndCommandCount;
  236.     SndCommand *SoundCommand;
  237.     SoundHeaderPtr sndHeadPtr;
  238.     
  239.     HLock   (sndHandle);
  240.     i = (short *) *sndHandle; /* get first word of snd resource */
  241.         
  242.     if (*i != 1)         /* deal only with format 1 snd resource    */
  243.         return (-1); /* return error (-1) for other snd types */
  244.     i++;
  245.     synthCount = *i;     /* count of modifiers/synthesizers in resource */
  246.     i++;
  247.     i += (synthCount * (1 + 2)); /* jump over modifiers/synthesizers, */ 
  248.                                      /* so we can get at the sound commands */
  249.     sndCommandCount = *i;        /* count of sound commands in resource */
  250.     i++;
  251.        SoundCommand = (SndCommand*) i; /* get reference to 1st sound command */
  252.      
  253.     sndDescriptP->descSize  = sizeof(SoundDescription);
  254.                                                  /*size of SoundDescription*/
  255.     sndDescriptP->resvd1        = 0;     /* reserved by Apple       */
  256.     sndDescriptP->resvd2        = 0;     /* reserved by Apple       */
  257.     sndDescriptP->version       = 0;     /* data version        */
  258.     sndDescriptP->revlevel      = 0;     /* codec version       */
  259.     sndDescriptP->vendor        = 0;     /* codec vendor        */
  260.     sndDescriptP->compressionID     = 0;     /* sound compression 0=none*/
  261.     sndDescriptP->packetSize    = 0;     /* compression packet size,*/
  262.                                                  /* 0 if not compressed */
  263.     sndDescriptP->numChannels   = 1;  /* number of channels of sound*/
  264.     sndDescriptP->sampleSize    = 8;  /* number of bits per sample  */
  265.     sndDescriptP->dataFormat    = 'raw '; /* uncompressed           */
  266.     
  267.     /* coerce in order to access sample rate, frame count, & data offsets*/
  268.     sndHeadPtr  = (SoundHeaderPtr) (*sndHandle + SoundCommand->param2);
  269.     sndDescriptP->sampleRate    = sndHeadPtr->sampleRate;
  270.                                                      /*sample rate of data*/
  271.     *frameCount = sndHeadPtr->length;        /* number of frames */
  272.     *dataOffset = sndHeadPtr->sampleArea - *sndHandle; /* offset to data */
  273.     
  274.     HUnlock(sndHandle);
  275. } /*CreateSndDescriptor*/
  276.  
  277.  
  278.  
  279.